/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package pgentity.services.restores;

import config.CFAchievements;
import config.PGConfig;
import db.DBContext;
import db.PGKeys;
import db.RedisKey;
import java.util.List;
import java.util.Map;
import org.json.simple.JSONObject;
import pgentity.Achievement;
import pgentity.BoxEgg;
import pgentity.CoinCard;
import pgentity.Cote;
import pgentity.CoteList;
import pgentity.Dog;
import pgentity.FindEggs;
import pgentity.FriendList;
import pgentity.Inventory;
import pgentity.MainQuestLine;
import pgentity.Minigame;
import pgentity.NPCList;
import pgentity.Penguin;
import pgentity.PenguinList;
import pgentity.Penguindex;
import pgentity.UIData;
import pgentity.UsedGiftCode;
import pgentity.User;
import pgentity.UserGifts;
import pgentity.UserList;
import pgentity.UserSettings;
import pgentity.UserTempData;
import pgentity.events.release_event.ReleaseEventServices;
import pgentity.services.QuestServices;
import pgentity.services.UserServices;
import share.PGHelper;
import share.PGMacro;

/**
 *
 * @author KieuAnh
 */

class V0_Restorer implements Restorer
{
    protected V0_Restorer()
    {
        super();
    }
    
    private static final V0_Restorer inst = new V0_Restorer();
    
    public static V0_Restorer inst()
    {
        return inst;
    }
    
    @Override
    public void restore(String uid, JSONObject data, long now) {
    // destroy user before restore
        UserServices.inst().destroyUser(uid);

        restoreUser(uid, (Map) data.get(PGMacro.USER));
        restoreNPCs(User.getUser(uid), PGHelper.toInteger(data.get(PGMacro.NPC_LIST)), now);
        restoreFriendList(uid, (List) data.get(PGMacro.FRIEND_LIST));
        restoreMainQuest(uid, (Map) data.get(PGMacro.MAIN_QUEST));
        restoreAchievements(uid, (Map) data.get(PGMacro.ACHIEVEMENTS));
        restoreTemp(uid, (Map) data.get(PGMacro.USER_TEMP_DATA));
        restoreSettings(uid, (Map) data.get(PGMacro.SETTINGS));
        restorePenguindex(uid, (List) data.get(PGMacro.PENGUINDEX));
        restoreUI(uid, (Map) data.get(PGMacro.UIDATA));
        restoreInventory(uid, (Map) data.get(PGMacro.INVENTORY));
        restoreGifts(uid, (List) data.get(PGMacro.GIFTS));
        restoreUsedGiftcode(uid, (List) data.get(PGMacro.USED_GIFTCODE));
        restoreCoinCard(uid, (Map) data.get(PGMacro.COIN_CARD));
        restoreFindEggsNPC(uid, (Map) data.get(PGMacro.NPC_FIND_EGGS));

        restoreCoteList(uid, (List) data.get(PGMacro.COTE));
        restoreReleaseEvent(uid, (Map) data.get(PGMacro.RELEASE_EVENT), now);
    }
    
    protected void restoreUser(String uid, Map<String, String> data)
    {
//        EntityPool.inst().remove(User.class, uid);
        DBContext.Redis().hset(User.redisKey(uid), data);
        UserList.getList(UserList.ListType.ALL_USER).add(uid);
    }
    
    protected void restoreNPCs(User user, int nNPC, long now)
    {
        if (nNPC > 0)
        {
            UserServices.inst().initNPCs(user, now);
        }
    }
    
    protected void restoreFriendList(String uid, List<String> friendIDs)
    {
        FriendList.destroy(uid);
        String[] arrFIDs = friendIDs.toArray(new String[friendIDs.size()]);
        FriendList.getFriendList(uid).add(arrFIDs);
        
        List<String> npcIDs = NPCList.getNPCList(uid).getAll();
        String[] npcIDArr = npcIDs.toArray(new String[npcIDs.size()]);
        FriendList.getFriendList(uid).add(npcIDArr);
    }
    
    protected void restoreMainQuest(String uid, Map<String, Object> data)
    {
        Iterable<String> questLines = PGConfig.inst().getMainQuest();
        for (String qLine : questLines)
        {
            restoreQuestLine(uid, qLine, (Map) data.get(qLine));
        }
    }
    
    protected void restoreQuestLine(String uid, String qLine, Map<String, Object> data)
    {
//        EntityPool.inst().remove(MainQuestLine.class, uid, qLine);
        DBContext.Redis().hset(MainQuestLine.redisKey(uid, qLine), (Map) data.get("data"));
    }
    
    protected void restoreAchievements(String uid, Map<String, Object> data)
    {
        CFAchievements achConfig = PGConfig.inst().getAchievements();
        for (String achID : achConfig) {
            if (data.containsKey(achID))
            {
                try
                {
                    restoreAch(uid, achID, (Map) data.get(achID));
                }
                catch (Exception ex)
                {
                    // try next
                }
            }
        }
    }
    protected void restoreAch(String uid, String achID,
            Map<String, Object> data)
    {
//        EntityPool.inst().remove(Achievement.class, uid, achID);
        DBContext.Redis().hset(Achievement.redisKey(uid, achID), (Map) data.get("data"));
        
        Achievement ach = Achievement.getAchievements(uid, achID);
        ach.getLogger().restore((Map) data.get("log"));
    }
    
    protected void restoreTemp(String uid, Map<String, String> data)
    {
//        EntityPool.inst().remove(UserTempData.class, uid);
        DBContext.Redis().hset(UserTempData.key(uid), data);
    }
    
    protected void restoreSettings(String uid, Map<String, String> data)
    {
//        EntityPool.inst().remove(UserSettings.class, uid);
        DBContext.Redis().hset(UserSettings.redisKey(uid), data);
    }
    
    protected void restorePenguindex(String uid, List<String> data)
    {
        RedisKey redisKey = Penguindex.redisKey(uid);
        DBContext.Redis().del(redisKey);
        String[] arrData = data.toArray(new String[data.size()]);
        DBContext.Redis().sadd(redisKey, arrData);
    }
    
    protected void restoreUI(String uid, Map<String, String> data)
    {
//        EntityPool.inst().remove(UIData.class, uid);
        DBContext.Redis().hset(UIData.redisKey(uid), data);
    }
    
    protected void restoreInventory(String uid, Map<String, Object> data)
    {
        RedisKey rKey = Inventory.redisKey(uid);
        if (data.containsKey(PGMacro.DATA))
        {
            Map<String, String> invData = (Map) data.get(PGMacro.DATA);
            DBContext.Redis().hset(rKey, invData);
        }
            
        RedisKey eggStoreKey = rKey.getChild(PGKeys.FD_EGGS);
        restoreEggStore(eggStoreKey, (Map) data.get(PGMacro.EGGS));
    }
    
    protected void restoreEggStore(RedisKey key, Map<String, String> data)
    {
//        EntityPool.inst().remove(EggStore.class, key);
        DBContext.Redis().hset(key, data);
    }
    
    protected void restoreGifts(String uid, List<String> data)
    {
        RedisKey redisKey = UserGifts.redisKey(uid);
        String[] arrGIDs = data.toArray(new String[data.size()]);
        DBContext.Redis().del(redisKey);
        DBContext.Redis().sadd(redisKey, arrGIDs);
    }
    
    protected void restoreUsedGiftcode(String uid, List<String> data)
    {
        if (data == null || data.isEmpty())
            return;
        
        RedisKey redisKey = UsedGiftCode.redisKey(uid);
        DBContext.Redis().del(redisKey);
        String[] arrData = data.toArray(new String[data.size()]);
        DBContext.Redis().sadd(redisKey, arrData);
    }
    
    protected void restoreCoteList(String uid, List<Map<String, Object>> coteData)
    {
        DBContext.Redis().del(CoteList.redisKey(uid));
        CoteList coteList = CoteList.getCotes(uid);
        String[] coteIDs = new String[coteData.size()];
        for (int i = 0; i < coteData.size(); i++) {
            coteIDs[i] = PGKeys.randomKey();
            coteList.append(coteIDs[i]);

            restoreCote(uid, coteIDs[i], coteData.get(i));
        }
    }
    
    protected void restoreCote(String uid, String coteID, Map<String, Object> data)
    {    
        Map<String, Object> coteData = (Map) data.get(PGMacro.COTE);
        DBContext.Redis().hset(Cote.redisKey(uid, coteID), (Map) coteData.get(PGMacro.DATA));
        
        Map<String, String> eggsData = (Map) coteData.get(PGMacro.EGGS);
        RedisKey eggStoreKey = Cote.redisKey(uid, coteID).getChild(PGKeys.FD_EGGS);
        restoreEggStore(eggStoreKey, eggsData);
        
        restoreBoxegg(uid, coteID, (Map) data.get(PGMacro.BOXEGG));
        restorePenguinList(uid, coteID, (List) data.get(PGMacro.PENGUIN_LIST));
        restoreDog(uid, coteID, (Map) data.get(PGMacro.DOG));
    }
    
    protected void restoreBoxegg(String uid, String coteID, Map<?, ?> data) {
        Map<String, String> beData = (Map) data.get(PGMacro.DATA);
        DBContext.Redis().hset(BoxEgg.redisKey(uid, coteID), beData);
        
        Map<String, String> eggsData = (Map) data.get(PGMacro.EGGS);
        RedisKey esKey = BoxEgg.redisKey(uid, coteID).getChild(PGKeys.FD_EGGS);
        restoreEggStore(esKey, eggsData);
    }
    
    protected void restorePenguinList(String uid, String coteID,
            List<Map<String, String>> data)
    {
        String[] pIDs = new String[data.size()];
        for (int i = 0; i < data.size(); i++) {
            pIDs[i] = PGKeys.randomKey();
            
            restorePenguin(uid, coteID, pIDs[i], data.get(i));
        }
        
        PenguinList.destroyList(uid, coteID);
        PenguinList.getPenguinList(uid, coteID).add(pIDs);
    }
    
    protected void restorePenguin(String uid, String coteID, String pID,
            Map<String, String> data)
    {
        DBContext.Redis().hset(Penguin.redisKey(uid, coteID, pID), data);
    }
    
    protected void restoreDog(String uid, String coteID, Map<String, String> data)
    {
        DBContext.Redis().hset(Dog.redisKey(uid, coteID), data);
    }
    
    protected void restoreReleaseEvent(String uid, Map<String, Object> data, long now)
    {
        if (data == null)
            return;
        
        ReleaseEventServices.SERVICES.restore(uid, data, now);
    }
    
    protected void restoreCoinCard(String uid, Map<String, String> data)
    {
        restoreHashData(CoinCard.key(uid), data);
    }
    
    protected void restoreFindEggsNPC(String uid, Map<String, String> data)
    {
        restoreHashData(FindEggs.key(uid), data);
    }
    
    protected void restoreUrgentQuest(String uid, Map<String, String> data)
    {
        QuestServices.inst().restoreUrgentQuest(uid, data);
    }
    
    protected  void restoreMinigame(String uid, Map<String, String> data)
    {
        restoreHashData(Minigame.key(uid), data);
    }
    
    protected void restoreHashData(RedisKey key, Map<String, String> data)
    {
        if (PGHelper.isNullOrEmpty(key.toString()) || PGHelper.isNullOrEmpty(data))
            return;
        
        DBContext.Redis().hset(key, data);
    }
}
